/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved
*
*  This file is part of the GroupMe! Project. You can utilize
*  software of the GroupMe! project under the terms of the 
*  GNU Lesser General Public License as published by the
*  Free Software Foundation in version 2.1.
* 
*  The GNU Lesser General Public License can be found at:
*  http://www.gnu.org/licenses/lgpl.html
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.export.rdf;

import java.io.StringReader;
import java.net.URI;
import java.util.Collection;

import javax.sql.DataSource;

import net.groupme.export.IResourceExport;
import net.groupme.export.Utils;
import net.groupme.export.constants.ResourceConstants;
import net.groupme.export.constants.TagConstants;
import net.groupme.model.Group;
import net.groupme.model.Resource;
import net.groupme.model.Tag;
import net.groupme.model.rdf.Statement;

import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.vocabulary.DC;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;

/**
 * This class provides...
 *
 * @author Daniel Plappert
 * @version 0.1
 */
public class ResourceExport implements IRdfDataExport, IResourceExport {
    
    private Collection<Resource> data = null;
    private DataSource ds = null;
    
    /**
     * Creates a new instance of ResourceExport
     */
    protected ResourceExport() {}
    
    
    /**
     *
     *
     * @param DataSource
     */
    public ResourceExport(DataSource ds) {
        this.ds = ds;
    }
    
    
    /**
     *
     *
     * @param Collection<Resource>
     */
    public void setData(Collection<Resource> data) {
        this.data = data;
    }
    
    
    /**
     *
     *
     * @param Model
     */
    public void exportData(Model model, boolean exportAll) {
        
        com.hp.hpl.jena.rdf.model.Resource tempRes = null;
        Literal tempLit = null;
        //TagExport exportTag = new TagExport(ds);
        
        for(Resource tempData : data) {
            
            tempRes = model.createResource(tempData.getURI().toString());
            tempRes.addProperty(RDF.type, model.createResource( Utils.getUriByStringType(tempData.getType()) ));
            
            // name attribute
            tempLit = model.createTypedLiteral(tempData.getName());
            tempRes.addProperty(DC.title, tempLit);
            
            // description attribute
            tempLit = model.createTypedLiteral(tempData.getDescription());
            tempRes.addProperty(DC.description, tempLit);
            
            // url attribute
            if(tempData.getURL() != null){
            	tempLit = model.createTypedLiteral(tempData.getURL().toString());
            	tempRes.addProperty(ResourceConstants.resourceURLProperty, tempLit);
            	tempRes.addProperty(OWL.sameAs, model.createResource(tempLit.getString()));
            }            
            
            // export groups the resource belongs to
            if(exportAll){
            	exportGroupRelation(model, tempRes, tempData.getURI());
            	
                // export all tags related to this resource
                exportTagAssignments(tempData, tempRes, model);
                
                //old:
                /*exportTagRelation(model, tempRes, tempData.getTags());           
                exportTag.setData(tempData.getTags());
                exportTag.exportData(model, true);*/
            }
            
            // export all related statements
            exportStatements(model, tempRes, tempData.getStatements());
            
        }
        
    }    
    
    /**
     * Export TagAssignments to the given Jena Model.
     * @param resource the resource that is tagged
     * @param model the Jena Model that should be filled
     */
    private void exportTagAssignments(Resource resource, com.hp.hpl.jena.rdf.model.Resource asJenaResource, Model model){
    	for(TaggingContext tempTaggingContext : Utils.getTaggingContextByResourceId(ds,resource.getId())) {

             com.hp.hpl.jena.rdf.model.Resource blankNode = model.createResource();
             blankNode.addProperty(RDF.type, model.createResource(TagConstants.taggingContextUri));
             if(tempTaggingContext.getGroup() != null){//if groups are tagged directly then tempTaggingContext.getGroup() is null
            	 blankNode.addProperty(TagConstants.groupProperty, model.createResource(tempTaggingContext.getGroup().toString()));
             }
             blankNode.addProperty(TagConstants.userProperty, model.createResource(tempTaggingContext.getUser().toString()));
             blankNode.addProperty(TagConstants.tagProperty, model.createResource(tempTaggingContext.getUser().toString()));
             blankNode.addProperty(TagConstants.resourceProperty, model.createResource(tempTaggingContext.getResource().toString()));
             blankNode.addProperty(TagConstants.importanceProperty, model.createTypedLiteral(tempTaggingContext.getImportance()));
             blankNode.addProperty(TagConstants.creationDateProperty, model.createTypedLiteral(tempTaggingContext.getCreationDate(), XSDDatatype.XSDdate));

             asJenaResource.addProperty(ResourceConstants.hasTagProperty, blankNode);
         }
    }
    
    
    /**
     *
     *
     * @param Model
     * @param Resource
     * @param Collection<Statement>
     */
    private void exportStatements(Model model, com.hp.hpl.jena.rdf.model.Resource res, Collection<Statement> tempCollection) {
        
        Model tempModel; StringReader reader;
        
        for(Statement tempStatement : tempCollection) {
            
            if ( tempStatement.getDatatype().equals("rdf") ) {
                //TODO: hier wird nur ein Subject in gesamten RDF erwartet. Ist das immer so?
                tempModel = ModelFactory.createDefaultModel();
                reader = new StringReader(tempStatement.getObject());
                tempModel.read(reader, "");
                model.union(tempModel);
                res.addProperty(model.createProperty(tempStatement.getProperty()), 
                    tempModel.listStatements().nextStatement().getSubject());
                
            } else {
                
                res.addProperty(model.createProperty(tempStatement.getProperty()),
                    model.createTypedLiteral(tempStatement.getObject(), tempStatement.getDatatype()));
                
            }
        }
        
    }
    
    
    /**
     *
     *
     * @param Model
     * @param Resource
     * @param URI
     */
    private void exportGroupRelation(Model model, com.hp.hpl.jena.rdf.model.Resource res, URI uri) {
        
        for(Group group : Utils.getGroupsByResourceUri(ds, uri)) {
            res.addProperty(ResourceConstants.isInGroupProperty, model.createResource(group.getURI().toString()));
        }

    }
    
    
    /**
     *
     *
     * @param Model
     * @param Resource
     * @param Collection<Tag>
     */
    private void exportTagRelation(Model model, com.hp.hpl.jena.rdf.model.Resource res, Collection<Tag> tagCollection) {
        
        for(Tag tag : tagCollection) {
            res.addProperty(ResourceConstants.hasTagProperty, 
                model.createResource(tag.getURI().toString()));
        }
        
        
    }
    
    
}
